package net.comm.web.base;

import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.HashMap;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionServlet;

import net.comm.common.ReturnMessage;
import net.comm.page.PageCtr;
import net.comm.util.FormatUnit;
import net.comm.util.HtmlMessageBox;
import net.comm.util.HtmlMessageProcess;
import net.comm.util.StringUtil;

/**
 * 所有控制操作的Action的抽象基类
 * 
 * @author 
 * @version 1.0
 * 
 *          TODO
 */
public abstract class AbstractBaseAction extends Action {

	// 反射机制查找方法中的方法名的高速缓存,用来存储调用过的方法名
	protected HashMap methodMap = new HashMap();

	// 每次web请求的上下文环境
	protected ServletContext context;

	protected static final Class[] types = { ActionMapping.class,
			ActionForm.class, HttpServletRequest.class,
			HttpServletResponse.class };

	//
	protected static final String HTMLMESSAGEPROCESS_STR = "hmp";

	// web请求表单操作字段的键值，每个页面表单的隐藏操作字段必须为action
	protected static final String ACTION_KEY = "action";

	// session中保存当前登陆用户的键值
	protected static final String SESSION_USER_KEY = "userID";

	// 操作结果跳转页面的forward
	protected static final String MESSAGE_PAGE = "oprResultFwd";

	// 非法操作跳转页面的forward
	protected static final String INVALID_OPR_PAGE = "invalidOprFwd";

	// 系统错误跳转页面的forward
	protected static final String SYSTEM_ERR_PAGE = "sysErrFwd";

	// session过期的跳转页面的forward
	protected static final String SESSION_ERR_PAGE = "sessionErrFwd";
	/**
	 * 保存在request中的错误信息标志
	 */
	protected static final String PAGE_ERROR = "pageError";
	// 登陆标志,默认为false(未登陆)
	protected boolean loginedFlag = true;

	// 是否需要session验证标志,默认是true(需要进行session验证)
	protected boolean sessionFlag = false;

	// 是否需要权限验证标志,默认是flase(不需要权限验证)
	protected boolean accessFlag = false;

	/**
	 * 查询页面最后一条记录键值参数名
	 */
	protected static final String KEY = "_key_";
	protected static final String LAST_KEY = "_lastkey_";
	protected static final String PAGE_KEY = "_page_";

	/**
	 * 默认构造函数
	 */
	public AbstractBaseAction() {
	}

	/**
	 * 构造函数,初始化session验证标志以及权限验证标志
	 * 
	 * @param sessionFlag
	 * @param accessFlag
	 * @param dispatchAction
	 */
	public AbstractBaseAction(boolean sessionFlag) {
		this.sessionFlag = sessionFlag;
	}

	public void setServlet(ActionServlet actionServlet) {
		super.setServlet(actionServlet);
		context = actionServlet.getServletContext();
	}

	/**
	 * 获取request对象中的<code>ACTION_KEY</code>键值
	 * 
	 * @param request
	 * @return
	 */
	public String getAction(HttpServletRequest request) {
		return (String) request.getParameter(ACTION_KEY);
	}

	/**
	 * 设置action的值
	 * 
	 * @param request
	 *            WEB请求request对象
	 * @param action
	 *            请求表单中action字段
	 */
	protected void setAction(HttpServletRequest request, String action) {
		request.setAttribute(ACTION_KEY, action);
	}

	/**
	 * @see org.
	 * @param mapping
	 *            The ActionMapping used to select this instance
	 * @param form
	 *            The optional ActionForm bean for this request (if any)
	 * @param request
	 *            The HTTP request we are processing
	 * @param response
	 *            The HTTP response we are creating
	 * 
	 * @exception Exception
	 *                if an exception occurs
	 */
	public ActionForward execute(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response) {
		ActionForward af = null;

		try {
			// 根据session标志进行用户session验证
			// request.setCharacterEncoding("UTF-8");
			
			if (this.sessionFlag) {
				if (!isLogin(request)) {

					af = mapping.findForward(SESSION_ERR_PAGE);
				}
			}else{
				
			}

			if ((af = startAction(mapping, form, request, response)) != null) {
				return af;
			}

			return dispatchAction(mapping, form, request, response);

		} catch (Exception ex) {
			ex.printStackTrace();
		}

		return mapping.findForward(SYSTEM_ERR_PAGE);
	}

	/**
	 * 
	 * @param mapping
	 * @param actionForm
	 * @param request
	 * @param response
	 */
	protected ActionForward startAction(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response) {
		return null;
	}

	/**
	 * 根据action参数,查找调用具体Action中的方法名
	 * 
	 * @param mpg
	 * @param form
	 * @param request
	 * @param response
	 * @param action
	 * @return
	 * @throws Exception
	 */
	private ActionForward dispatchAction(ActionMapping mpg, ActionForm form,
			HttpServletRequest request, HttpServletResponse response)
			throws Exception {
		Method method = null;
		ActionForward forward = null;
		try {
//			System.out.println("url=" + request.getRequestURL());
//			System.out.println("QueryString=" + request.getQueryString());
			
			method = findMethod(getAction(request));
			Object[] args = { mpg, form, request, response };
			forward = (ActionForward) method.invoke(this, args);
		} catch (ClassCastException e) {
			e.printStackTrace();
			throw new Exception(e);
		} catch (IllegalAccessException e) {
			e.printStackTrace();
			throw new Exception(e);
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
			throw new Exception(e);
		}
		return forward;
	}

	/**
	 * 使用HtmlMessageBox返回消息到客户端
	 * 
	 * @param hmb
	 *            HtmlMessageBox对象(客户端显示消息方式)
	 * @param request
	 *            HttpServletRequest对象
	 * @param response
	 *            HttpServletResponse对象
	 * @param mpg
	 *            请求跳转对象
	 * @return
	 */
	protected ActionForward showMsg(HtmlMessageBox hmb,
			HttpServletRequest request, HttpServletResponse response,
			ActionMapping mapping) {
		String htmlCode = HtmlMessageProcess.generateHTML(request, hmb);
		int alertType = hmb.getAlertType();

		request.setAttribute("htmlCode", htmlCode);
		request.setAttribute("alertType", String.valueOf(alertType));
		return mapping.findForward(MESSAGE_PAGE);
	}

	/**
	 * 
	 * @param request
	 * @param userInfo
	 */
	protected void saveUserInfo(HttpServletRequest request, Object userInfo) {
		HttpSession session = request.getSession(true);
		session.removeAttribute(SESSION_USER_KEY);
		session.setAttribute(SESSION_USER_KEY, userInfo);
		this.loginedFlag = true;
	}

	/**
	 * 
	 * @param request
	 * @return
	 */
	protected Object getUserInfo(HttpServletRequest request) {
		HttpSession session = request.getSession(true);
		return session.getAttribute(SESSION_USER_KEY);
	}

	/**
	 * 
	 * @param request
	 * @return
	 */
	private boolean isLogin(HttpServletRequest request) {
		if (getUserInfo(request) != null) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 
	 * @param name
	 * @return
	 * @throws NoSuchMethodException
	 */
	private Method findMethod(String action) throws NoSuchMethodException {
		Method method = (Method) methodMap.get(action);
		if (method == null) {
			method = this.getClass().getMethod(action, types);
			synchronized (methodMap) {
				methodMap.put(action, method);
			}
		}
		try {
			return method;
		} finally {
			method = null;
		}
	}

	/**
	 * 从request中获取页面信息生成分页对象
	 * 
	 * @param request
	 * @return 
	 */
	protected PageCtr getPageFromReq(HttpServletRequest request) {
		PageCtr page = new PageCtr(1, 10, "N", " 1=1 ");

		page.setDirection(FormatUnit.getInstance().format(
				request.getParameter("direction")));
		String tmpStr = FormatUnit.getInstance().format(
				request.getParameter("currPage"));
		if (tmpStr.length() > 0) {
			page.setCurPage(Integer.parseInt(tmpStr));
		} else {
			page.setCurPage(1);
		}
		return page;
	}
	/**
	 * 从request中获取页面信息生成分页对象
	 * 
	 * @param request
	 * @return 
	 */
	protected PageCtr getPageFromReq(HttpServletRequest request,int line) {
		
		PageCtr page = new PageCtr(1, line, "N", " 1=1 ");

		page.setDirection(FormatUnit.getInstance().format(
				request.getParameter("direction")));
		String tmpStr = FormatUnit.getInstance().format(
				request.getParameter("currPage"));
		if (tmpStr.length() > 0) {
			page.setCurPage(Integer.parseInt(tmpStr));
		} else {
			page.setCurPage(1);
		}
		return page;
	}
	
	/**
	 * 调用StringUtil.getValue(value)来避免取到null值
	 * 
	 * @param request
	 *            HttpServletRequest对象
	 * @return
	 */
	protected String getReqParam(HttpServletRequest request, String name) {

		return StringUtil.getValue(request.getParameter(name));

	}

	/**
	 * 使用struct的错误机制把错误信息保存到request中
	 * 
	 * @param request
	 * @param key
	 * @param error
	 */
	protected void setErrorToRequest(HttpServletRequest request,
			ReturnMessage msg) {
		ActionErrors errors = new ActionErrors();
		ActionError error = new ActionError(msg.getResultCode()[0], msg
				.getMsg());
		errors.add(PAGE_ERROR, error);
		saveErrors(request, errors);
	}

	/**
	 * 把request中提交的值赋值到bean中
	 * 
	 * @param bean
	 *            java bean对象
	 * @param prefix
	 *            赋值参数前缀
	 * @param suffix
	 *            赋值参数后缀
	 * @param request
	 *            HttpServletRequest对象
	 */
	public void populate(Object bean, String prefix, String suffix,
			HttpServletRequest request) {
		HashMap properties = new HashMap();
		Enumeration names = null;
		names = request.getParameterNames();

		if (names != null) {
			while (names.hasMoreElements()) {
				String name = (String) names.nextElement();
				if (prefix != null) {
					if (!name.startsWith(prefix)) {
						continue;
					}
				}

				if (suffix != null) {
					if (!name.endsWith(suffix)) {
						continue;
					}
				}

				properties.put(name, getReqParam(request, name));
			}
		}

		/**
		 * 设置BEAN的对应的属性
		 */
		try {
			BeanUtils.populate(bean, properties);
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new RuntimeException(ex);
		}

	}

}
